<?php
namespace mytp;

// 获取 $_GET/$_POST的 json数据, 然后拼成 sql语句
class Model {
  protected $db;
  protected $table = '';
  protected $options = [];
  
  public function __construct(){
    $this->db = DB::getInstance();
    $this->initTable();
    $this->resetOption();
  }

  // 初始化 table名
  public function initTable() {
    if($this->table === '') {
      $this->table = strtolower(basename(get_class($this)));
      $this->table = $this->db->getConfig('prefix') . $this->table;
    }
  }

  // 重置选项
  public function resetOption() {
    $this->options = [
      'where' => '',
      'order' => '',
      'limit' => '',
      // 绑定的参数
      'data' => []
    ];
  }

  public function getTable() {
    return $this->table;
  }

   // 拼接查的 sql语句
   protected function buildSelect(array $field = []) {
    $field = empty($field)? '*' : '`'.implode('`,`', $field).'`';
    $table = $this->table;
    $where = $this->options['where'];
    $order = $this->options['order'];
    $limit = $this->options['limit'];
    return "select $field from `$table` $where $order $limit";
  }

  // 根据拼接的 sql语句获取数据
  public function get(array $field = []) {
    $sql = $this->buildSelect($field);
    $data = $this->db->fetchAll($sql, $this->options['data']);
    $this->resetOption();
    return $data;
  }

  public function buildWhere($field, $op = '=', $value = null, $join = 'and') {
    if(is_array($field)){
      foreach($field as $index => $value){
        $this->where($index, '=', $value);
      }
      return ;
    } elseif (is_null($value)) {
      $value =  $op;
      $op = '=';
    }
    if(empty($this->options['where'])){
      $join = 'where';
    }
    $this->options['where'] .= "$join `$field` $op ? ";
    $this->options['data'][] = "$value";  
  }

  public function where($field, $op = '=', $value = null) {
    $this->buildWhere($field, $op, $value, 'and');
    // 返回自身以便链式调用
    return $this;
  }

  public function orWhere($field, $op = '=', $value = null) {
    $this->buildWhere($field, $op, $value, 'or');
    return $this;
  }

  // 一参为待排序字段, 二参为排序方式
  public function order($field, $sort = 'ASC') {
    $this->options['order'] = "order by `$field` $sort";
    return $this;
  }

  // 一参为偏移量, 二参为限制的条目
  public function limit($offset, $limit = '') {
    if($limit){
      $limit = ", $limit";
    }
    $this->options['limit'] = 'limit ' . $offset . $limit;
    return $this;
  }

  // 显示当前拼接成的 sql语句
  public function ShowSql() {
    return $this->buildInsert();
  }

  // 一参为添加的字段, 二参为插入的条数
  public function buildInsert(array $fields = [], $count = 1) {
    // 生成字段数量的 ? 占位符
    $value = array_fill(0 , count($fields), '?');
    // 将值拼接成"(?, ?)"的形式
    $value = '('.implode(',', $value).')';
    // 根据插入的条数 $count, 将值拼接成 "(?, ?), (?, ?)" 的形式
    $value = implode(',', array_fill(0, $count, $value));
    // var_dump($fields);
    $fields = '`'.implode('`,`', $fields). '`';
    $table = $this->table;
    return "INSERT INTO `$table` ($fields) VALUES $value";
  }

  public function insert(array $data = []) {
    if(isset($data[0])&&is_array($data[0])) {
      // 多条数据时
      $sql = $this->buildInsert(array_keys($data[0]), count($data));
      // 将二维数组转换为一维数组
      $data = array_reduce($data, function ($carry, $item) {
        return array_merge($carry, array_values($item)); 
      }, []);
    } else {
      $sql = $this->buildInsert(array_keys($data));
      $data = array_values($data);
    }
    // echo $sql."\n";
    // var_dump($data);
    $res = $this->db->execute($sql, $data);
    $this->resetOption();
    return $res;
  }

  // 添加后返回最后一条数据的 id值
  public function insertGetId(array $data = []) {
    $this->insert($data);
    return $this->db->lastInsertId(); 
  }

  public function buildUpdate(array $fields = []) {
    $fields = implode(',', array_map(function ($v) {
      return " `$v` = ?";
    }, $fields));
    $table = $this->table;
    $where = $this->options['where'];
    $order = $this->options['order'];
    $limit = $this->options['limit'];
    return "UPDATE `$table` SET $fields $where $order $limit";
  }

  public function update(array $data = []) {
    if(empty($this->options['where'])) {
      throw new \Exception('update()缺少条件');
    }
    $sql = $this->buildUpdate(array_keys($data));
    $data = array_merge(array_values($data), $this->options['data']);
    $res = $this->db->execute($sql, $data);
    $this->resetOption();
    return $res;
  }

  public function buildDelete() {
    $table = $this->table;
    $where = $this->options['where'];
    $order = $this->options['order'];
    $limit = $this->options['limit'];
    return "DELETE FROM `$table` $where $order $limit";
  }

  public function delete() {
    if(empty($this->options['where'])) {
      throw new \Exception('delete()缺少条件');
    }
    $sql = $this->buildDelete();
    $res = $this->db->execute($sql, $this->options['data']);
    $this->resetOption();
    return $res;
  }
}
?>